home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 015a / bootwhat.zip / PFDISK.C < prev    next >
C/C++ Source or Header  |  1990-12-17  |  16KB  |  566 lines

  1. /*
  2.  * pfdisk - Partition a Fixed DISK
  3.  *    by Gordon W. Ross, Jan. 1990
  4.  *
  5.  * See the file "pfdisk.doc" for user instructions.
  6.  *
  7.  * This program uses a simple, line-oriented interpreter,
  8.  * designed for both interactive and non-interactive use.
  9.  * To facilitate non-interactive use, the output from the
  10.  * 'L' (list partitions) command is carefully arranged so it
  11.  * can be used directly as command input.  Neat trick, eh?
  12.  */
  13.  
  14. char *versionString =
  15.   "# pfdisk version 1.2 by Gordon W. Ross  Aug. 1990\n";
  16.  
  17. /* These don't really matter.  The user is asked to set them. */
  18. #define DEFAULT_CYLS 306
  19. #define DEFAULT_HEADS 4
  20. #define DEFAULT_SECTORS 17
  21. #define PROMPT_STRING "pfdisk> "
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include "sysdep.h"
  27. #include "syscodes.h"
  28.  
  29. typedef unsigned char uchar;
  30. typedef unsigned int uint;
  31. typedef unsigned long ulong;
  32.  
  33. struct part {    /* An entry in the partition table */
  34.   uchar    active;        /* active flag (0x80 or 0) */
  35.   uchar    b_head;        /* begin head */
  36.   uchar    b_sec;        /*      sector */
  37.   uchar    b_cyl;        /*     cylinder */
  38.   uchar    sysid;        /* system id (see sysid.c) */
  39.   uchar    e_head;        /* end  head */
  40.   uchar    e_sec;        /* end    sector */
  41.   uchar    e_cyl;        /* end    cylinder */
  42.   /* These two are just longs, but this way is machine independent. */
  43.   uchar    lsBeg[4];    /* logical sectors, beginning */
  44.   uchar    lsLen[4];    /* logical sectors, length */
  45. };
  46.  
  47. #define LOC_PT        0x1BE
  48. #define LOC_NT        0x180
  49. #define LOC_GWR        0x1A0
  50. #define MAGIC_LOC    0x1FE
  51. #define MAGIC_0        0x55
  52. #define MAGIC_1        0xAA
  53. #define MAX_LINE    80
  54.  
  55. char    buffer[SECSIZE];    /* The boot block buffer */
  56. int    bufmod=0;        /* buffer modified... */
  57.         /* (zero means buffer is unmodified) */
  58. int    useNTable;        /* boot sector uses name table */
  59.  
  60. /* device parameters (force someone to set them!) */
  61. unsigned cyls = DEFAULT_CYLS;
  62. unsigned heads = DEFAULT_HEADS;
  63. unsigned sectors = DEFAULT_SECTORS;
  64.  
  65. char    *devname;        /* device name */
  66. char    cmdline[MAX_LINE];
  67. char    filename[80];        /* used by r/w commands */
  68. char    *prompt;        /* null if no tty input */
  69.  
  70. /* Some of these strings are used in more than one place.
  71.  * For consistency, I put a newline on all of them.
  72.  */
  73. char h_h[] = "? <enter>             : Help summary\n";
  74. char h_l[] = "L                     : List partition table\n";
  75. char h_1[] = "1 id first last name  : set partition 1\n";
  76. char h_2[] = "2,3,4 ... (like 1)    : set respective partition\n";
  77. char h_a[] = "A n                   : Activate partition n\n";
  78. char h_g[] = "G cyls heads sectors  : set disk Geometry\n";
  79. char h_i[] = "I                     : list known ID numbers\n";
  80. char h_r[] = "R [optional-file]     : Read  device (or specified file)\n";
  81. char h_w[] = "W [optional-file]     : Write device (or specified file)\n";
  82. char h_q[] = "Q[!]                  : Quit (! means force)\n";
  83.  
  84. char * helpTable[] = {
  85. h_h, h_l, h_1, h_2, h_a, h_g, h_i, h_r, h_w, h_q,
  86. "# (All command letters have lower-case equivalents.)\n",
  87. (char *) 0 }; /* This MUST have a zero as the last element */
  88.  
  89. char *BadArg="Error: bad argument: %s\n";
  90. char *WarnNotSaved =
  91.     "Warning, modified partition table not saved.\n";
  92.  
  93. help()
  94. {
  95.   char ** p;
  96.   for (p = helpTable; *p; p++)
  97.     printf(*p);
  98. }
  99.  
  100. /* forward declarations */
  101. void    checkValidity();
  102. char *    setPartition();
  103. char *    makeActive();
  104. char *    setGeometry();
  105. ulong    chs2long();
  106. char *    nameID();
  107. int    printIDs();
  108.  
  109. main(argc,argv)
  110. int    argc;
  111. char    *argv[];
  112. {
  113.   char    *cmdp;        /* points to command word */
  114.   char    *argp;        /* points to command args */
  115.  
  116.   /* check command line args (device name) */
  117.   if (argc != 2) {
  118.     usage(argv[0]);    /* See s-sysname.c */
  119.     exit(1);
  120.   }
  121.   devname = argv[1];
  122.  
  123.   /* Should we prompt? */
  124.   prompt = (isatty(fileno(stdin))) ? PROMPT_STRING : (char *) 0;
  125.  
  126.   /* Print version name. */
  127.   fputs(versionString, stderr);
  128.  
  129.   /* get disk parameters */
  130.   getGeometry(devname,&cyls,&heads,§ors);
  131.  
  132.   /* Get the boot block. */
  133.   if (getBBlk(devname, buffer) < 0)
  134.     fprintf(stderr,"%s: read failed\n", devname);
  135.   checkValidity();
  136.  
  137.   if (prompt) fprintf(stderr,"For help, enter: '?'\n");
  138.  
  139.  
  140.   /* Read and process commands a line at a time. */
  141.   while (1) {
  142.     if (prompt) fputs(prompt,stdout);
  143.     if (! fgets(cmdline, MAX_LINE, stdin)) break;
  144.  
  145.     /* Find beginning of command word */
  146.     cmdp = cmdline;
  147.     while (isspace(*cmdp)) cmdp++;
  148.  
  149.     /* find beginning of args */
  150.     argp = cmdp;
  151.     while (*argp && !isspace(*argp)) argp++;
  152.     while (isspace(*argp) || *argp=='=') argp++;
  153.  
  154.     switch (*cmdp) {
  155.  
  156.     case '\0':        /* blank line */
  157.     case '#':        /* line comment */
  158.       break;
  159.  
  160.     case '?': case 'h': case 'H':
  161.       help();
  162.       break;
  163.  
  164.     case '1':    /* set partition entry */
  165.     case '2': case '3': case '4':
  166.       argp = setPartition(cmdp, argp);
  167.       if (argp) {    /* arg list error */
  168.     fprintf(stderr,BadArg,argp);
  169.     fprintf(stderr,h_1);
  170.     fprintf(stderr,h_2);
  171.     break;
  172.       }
  173.       bufmod = 1;
  174.       break;
  175.  
  176.     case 'a': case 'A':    /* activate partition */
  177.       argp = makeActive(argp);
  178.       if (argp) {
  179.     fprintf(stderr,BadArg,argp);
  180.     fprintf(stderr,h_a);
  181.     break;
  182.       }
  183.       bufmod = 1;
  184.       break;
  185.  
  186.     case 'g': case 'G':    /* set disk parameters (Geometry) */
  187.       argp = setGeometry(argp);
  188.       if (argp) {    /* arg list error */
  189.     fprintf(stderr,BadArg,argp);
  190.     fprintf(stderr,h_g);
  191.       }
  192.       break;
  193.  
  194.     case 'i': case 'I':    /* List known ID numbers */
  195.       printIDs();
  196.       break;
  197.  
  198.     case 'l': case 'L':    /* List the partition table */
  199.       listPTable();
  200.       break;
  201.  
  202.     case 'q': case 'Q':    /* Quit */
  203.       if (bufmod && (cmdp[1]  != '!')) {
  204.     fprintf(stderr,"\007%s%s\n", WarnNotSaved,
  205.         "Use 'wq' or 'q!' (enter ? for help).");
  206.     break;
  207.       }
  208.       exit(0);
  209.       /*NOTREACHED*/
  210.  
  211.     case 'r': case 'R':    /* read from device or file */
  212.       if (sscanf(argp,"%80s",filename) == 1) {
  213.     /* Arg specified, read from filename */
  214.     if (getFile(filename, buffer, SECSIZE) < 0)
  215.       fprintf(stderr,"%s: read failed\n", filename);
  216.     bufmod = 1;
  217.       } else {
  218.     /* No arg, use device. */
  219.     if (getBBlk(devname, buffer) < 0)
  220.       fprintf(stderr,"%s: read failed\n", devname);
  221.     bufmod = 0;
  222.       }
  223.       checkValidity();
  224.       break;
  225.  
  226.     case 'w': case 'W':    /* Write to file or device */
  227.       if (sscanf(argp,"%80s",filename) == 1) {
  228.     /* Arg specified, write to filename */
  229.     if (putFile(filename, buffer, SECSIZE) < 0)
  230.       fprintf(stderr, "%s: write failed\n", filename);
  231.       } else {  /* No arg, use device. */
  232.     if (putBBlk(devname, buffer) < 0)
  233.       fprintf(stderr, "%s: write failed\n", devname);
  234.     bufmod = 0;
  235.       }
  236.       if (cmdp[1] == 'q' || cmdp[1] == 'Q') exit(0);
  237.       break;
  238.  
  239.     default:
  240.       fprintf(stderr,"'%c': unrecognized.  Enter '?' for help.\n", *cmdp);
  241.       break;
  242.  
  243.     } /* switch */
  244.   } /* while */
  245.   if (bufmod) fprintf(stderr, WarnNotSaved);
  246.   exit(0);
  247. } /* main */
  248.  
  249.  
  250. /* Check for valid boot block (magic number in last two bytes).
  251.  * Also, check for presence of partition name table.
  252.  */
  253. void checkValidity()
  254. {
  255.   /* Check the magic number. */
  256.   if ((buffer[MAGIC_LOC] & 0xFF) != MAGIC_0 ||
  257.       (buffer[MAGIC_LOC+1] & 0xFF) != MAGIC_1 ) {
  258.     /* The boot sector is not valid -- Fix it. */
  259.     buffer[MAGIC_LOC] = MAGIC_0;
  260.     buffer[MAGIC_LOC+1] = MAGIC_1;
  261.     bufmod = 1;
  262.     fprintf(stderr,
  263. "\n\tWarning:  The boot sector has an invalid magic number.\n\
  264. \tThe magic number has been fixed, but the other contents\n\
  265. \tare probably garbage.  Initialize using the command:\n\
  266. \t\tR boot-program-file    (i.e. bootmenu.bin)\n\
  267. \tthen set each partition entry if necessary.\n");
  268.   }
  269.  
  270.   /* Does it use a name table (for a boot menu)?
  271.    * My boot program does, and can be identified by
  272.    * finding my name in a particular (unused) area.
  273.    */
  274.   useNTable = !strcmp(&buffer[LOC_GWR], "Gordon W. Ross");
  275.  
  276. }
  277.  
  278. char * setPartition(cmdp,argp)    /* return string on error */
  279. char    *cmdp,*argp;
  280. {
  281.   struct part *pp;    /* partition entry */
  282.   char *    np;        /* name table pointer */
  283.   char *    newname;    /* name field */
  284.   int    index;        /* partition index (0..3) */
  285.   uint    id;        /* ID code (see syscodes.c) */
  286.   uint    first,last;    /* user supplied cylinders */
  287.   uint    c,h,s;        /* working cyl,head,sect, */
  288.   uint    len;        /* chars seen by sscanf */
  289.   ulong    lsbeg, lslen;    /* logical begin, length */
  290.  
  291.   /* Value check the index */
  292.   index = *cmdp - '1';
  293.   if (index < 0 || index > 3)
  294.     return("index");
  295.   pp = (struct part *) &buffer[LOC_PT + index * 16];
  296.   np = &buffer[LOC_NT + index * 8];
  297.  
  298.   /* Read System ID */
  299.   if (sscanf(argp,"%i%n", &id, &len) < 1)
  300.     return("id");
  301.   argp += len;
  302.  
  303.   /* If ID==0, just clear out the entry and return. */
  304.   if (id == 0) {
  305.     strncpy( (char *) pp, "", 16);
  306.     if (useNTable) strncpy( np, "", 8);
  307.     return((char *)0);
  308.   }
  309.  
  310.   /* Read first and last cylinder */
  311.   if (sscanf(argp,"%i%i%n",&first, &last, &len) < 2)
  312.     return("first last (missing)");
  313.   argp += len;
  314.  
  315.   /* Reasonable start,end cylinder numbers? */
  316.   if (first > last)    return("first > last");
  317.   if (first > 1023)    return("first > 1023");
  318.   if (last >= cyls)    return("last >= cyls");
  319.  
  320.   /* Get (optional) system name. */
  321.   if (*argp == '\n') {    /* no name given, use default */
  322.     newname = nameID(id);
  323.   } else {        /* use the given name */
  324.     /* skip leading space */
  325.     while (*argp == ' ') argp++;
  326.     newname = argp;
  327.     /* Remove newline from end */
  328.     while (isgraph(*argp)||*argp==' ') argp++;
  329.     *argp = '\0';
  330.     useNTable = 1;
  331.   }
  332.  
  333.   /* Set the ID and name. */
  334.   pp->sysid = id;
  335.   if (useNTable) {
  336.     strncpy(np, newname, 8);
  337.     strcpy(&buffer[LOC_GWR], "Gordon W. Ross");
  338.   }
  339.  
  340.   /* set beginning c,h,s */
  341.   c = first;
  342.   /* if c == 0, head == 1 (reserve track 0) */
  343.   h = (first) ? 0 : 1;
  344.   s = 1;
  345.   pp->b_cyl = c & 0xFF;
  346.   pp->b_head = h;
  347.   pp->b_sec = s | ((c >> 2) & 0xC0);
  348.   /* Set the logical sector begin field */
  349.   lsbeg = lslen = chs2long(c,h,s); /* using lslen as temp. */
  350.   pp->lsBeg[0] = lslen & 0xff; lslen >>= 8;
  351.   pp->lsBeg[1] = lslen & 0xff; lslen >>= 8;
  352.   pp->lsBeg[2] = lslen & 0xff; lslen >>= 8;
  353.   pp->lsBeg[3] = lslen & 0xff; lslen >>= 8;
  354.  
  355.   /* set ending c,h,s (last may be larger than 1023) */
  356.   c = (last>1023) ? 1023 : last; /* limit c to 1023 */
  357.   h = heads - 1; s = sectors;
  358.   pp->e_cyl = c & 0xFF;
  359.   pp->e_head = h;
  360.   pp->e_sec = s | ((c >> 2) & 0xC0);
  361.   /* Set the logical sector length field (using REAL end cylinder) */
  362.   lslen = chs2long(last,h,s) + 1 - lsbeg;
  363.   pp->lsLen[0] = lslen & 0xff; lslen >>= 8;
  364.   pp->lsLen[1] = lslen & 0xff; lslen >>= 8;
  365.   pp->lsLen[2] = lslen & 0xff; lslen >>= 8;
  366.   pp->lsLen[3] = lslen & 0xff; lslen >>= 8;
  367.  
  368.   return((char *)0);    /* success */
  369. } /* setPartition() */
  370.  
  371. char * makeActive(argp)    /* return error string or zero */
  372. char    *argp;
  373. {
  374.   struct part *pp;    /* partition entry */
  375.   int    i,act;        /* which one becomes active */
  376.  
  377.   if (sscanf(argp,"%d", &act) < 1)
  378.     return("missing index");
  379.   act--;            /* make it zero-origin */
  380.  
  381.   i=0; pp = (struct part *) &buffer[LOC_PT];
  382.   while (i<4) {
  383.     pp->active = 0;
  384.     if (i == act) {
  385.       if (pp->sysid == 0) return("partition empty");
  386.       pp->active = 0x80;
  387.     }
  388.     i++; pp++;
  389.   }
  390.   return((char *)0);
  391. }
  392.  
  393. char * setGeometry(argp)    /* return string on error */
  394. char    *argp;
  395. {
  396.   int    c,h,s;
  397.  
  398.   if (sscanf(argp,"%i%i%i", &c, &h, &s) < 3)
  399.     return("(missing)");
  400.   if (c<1) return("cyls");
  401.   if (h<1) return("heads");
  402.   if (s<1) return("sectors");
  403.   cyls=c; heads=h; sectors=s;
  404.   return((char *)0);
  405. }
  406.  
  407. listPTable()        /* print out partition table */
  408. {
  409.   struct part * pp;    /* partition table entry */
  410.   char    *name;
  411.   int    i;        /* partition number */
  412.   int    numActive=0;    /* active partition [1-4], 0==none */
  413.   uint    pbc,pbh,pbs;    /* physical beginning  c,h,s */
  414.   uint    pec,peh,pes;    /* physical ending     c,h,s */
  415.   uint    lbc,lbh,lbs;    /* logical beginning   c,h,s */
  416.   uint    lec,leh,les;    /* logical ending      c,h,s */
  417.   ulong    lsbeg,lslen;    /* logical sectors: begin, length */
  418.  
  419.   printf("# Partition table on device: %s\n", devname);
  420.   printf("geometry %d %d %d (cyls heads sectors)\n",
  421.      cyls, heads, sectors);
  422.   printf("#  ID  First(cyl)  Last(cyl)  Name     ");
  423.   printf("# start, length (sectors)\n");
  424.  
  425.   for (i=0; i<4; i++) {
  426.     pp = (struct part *) &buffer[LOC_PT + i * 16];
  427.  
  428.     if (pp->active) {
  429.       if(numActive)
  430.     fprintf(stderr,"Error: multiple active partitions.\n");
  431.       else numActive = i+1;
  432.     }
  433.  
  434.     /* physical beginning c,h,s */
  435.     pbc = pp->b_cyl & 0xff | (pp->b_sec << 2) & 0x300;
  436.     pbh = pp->b_head;
  437.     pbs = pp->b_sec & 0x3F;
  438.  
  439.     /* physical ending c,h,s */
  440.     pec = pp->e_cyl & 0xff | (pp->e_sec << 2) & 0x300;
  441.     peh = pp->e_head;
  442.     pes = pp->e_sec & 0x3F;
  443.  
  444.     /* compute logical beginning (c,h,s) */
  445.     lsbeg = ((((((pp->lsBeg[3] ) << 8 )
  446.         | pp->lsBeg[2] ) << 8 )
  447.         | pp->lsBeg[1] ) << 8 )
  448.         | pp->lsBeg[0] ;
  449.     long2chs(lsbeg, &lbc, &lbh, &lbs);
  450.     /* compute logical ending (c,h,s) */
  451.     lslen = ((((((pp->lsLen[3]) << 8 )
  452.         | pp->lsLen[2]) << 8 )
  453.         | pp->lsLen[1]) << 8 )
  454.         | pp->lsLen[0] ;
  455.     /* keep beginning <= end ... */
  456.     if (lslen > 0) long2chs(lsbeg+lslen-1, &lec, &leh, &les);
  457.     else       long2chs(lsbeg,       &lec, &leh, &les);
  458.  
  459.     if (useNTable)
  460.       name = &buffer[LOC_NT + i * 8];
  461.     else
  462.       name = nameID((uint) pp->sysid);
  463.  
  464.     /* show physical begin, logical end (works for cyl>1023) */
  465.     /*      #  ID  First(cyl)  Last(cyl)  Name... # ... */
  466.     printf("%d %3d   %4d       %4d       %-8.8s # %ld, %ld\n",
  467.        i+1, pp->sysid, pbc, lec, name, lsbeg, lslen );
  468.  
  469.     /* That's all, for an empty partition. */
  470.     if (pp->sysid == 0) continue;
  471.  
  472.     /*
  473.      * Now do some consistency checks...
  474.      */
  475.  
  476.     /* Same physical / logical beginning? */
  477.     if (pbc != lbc || pbh != lbh || pbs != lbs ) {
  478.       printf("# note: first(%d): ", i+1);
  479.       printf("phys=(%d,%d,%d) ",    pbc, pbh, pbs);
  480.       printf("logical=(%d,%d,%d)\n",lbc, lbh, lbs);
  481.     }
  482.     /* Same physical / logical ending? */
  483.     if (pec != lec || peh != leh || pes != les ) {
  484.       printf("# note:  last(%d): ", i+1);
  485.       printf("phys=(%d,%d,%d) ",    pec, peh, pes);
  486.       printf("logical=(%d,%d,%d)\n",lec, leh, les);
  487.     }
  488.  
  489.     /* Beginning on cylinder boundary? */
  490.     if (pbc == 0) { /* exception: start on head 1 */
  491.       if (pbh != 1 || pbs != 1) {
  492.     printf("# note: first(%i): ", i+1);
  493.     printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  494.     printf("should be (%d,1,1)\n", pbc);
  495.       }
  496.     } else { /* not on cyl 0 */
  497.       if (pbh != 0 || pbs != 1) {
  498.     printf("# note: first(%i): ", i+1);
  499.     printf("phys=(%d,%d,%d) ", pbc, pbh, pbs);
  500.     printf("should be (%d,0,1)\n", pbc);
  501.       }
  502.     }
  503.  
  504.     /* Ending on cylinder boundary? */
  505.     if (peh != (heads-1) || pes != sectors) {
  506.       printf("# note: last(%i): ", i+1);
  507.       printf("phys=(%d,%d,%d) ", pec, peh, pes);
  508.       printf("should be (%d,%d,%d)\n",
  509.          pec, heads-1, sectors);
  510.     }
  511.  
  512.   } /* for */
  513.   printf("active: %d  %s\n", numActive,
  514.      (numActive) ? "" : "(none)");
  515. } /* listPTable() */
  516.  
  517. ulong chs2long(c,h,s)
  518. uint c,h,s;
  519. {
  520.   ulong    l;
  521.   if (s<1) s=1;
  522.   l  = c; l *= heads;
  523.   l += h; l *= sectors;
  524.   l += (s - 1);
  525.   return(l);
  526. }
  527.  
  528. long2chs(ls, c, h, s)    /* convert logical sec-num to c,h,s */
  529. ulong    ls;        /* Logical Sector number */
  530. uint    *c,*h,*s;    /* cyl, head, sector */
  531. {
  532.   int    spc = heads * sectors;
  533.   *c = ls / spc;
  534.   ls = ls % spc;
  535.   *h = ls / sectors;
  536.   *s = ls % sectors + 1;    /* sectors count from 1 */
  537. }
  538.  
  539. char * nameID(n)
  540. unsigned int n;
  541. {
  542.   struct intString *is;
  543.  
  544.   is = sysCodes;
  545.   while (is->i) {
  546.     if (is->i == n) return(is->s);
  547.     is++;
  548.   }
  549.   if (!n) return(is->s);
  550.   return("unknown");
  551. }
  552.  
  553. int printIDs()        /* print the known system IDs */
  554. {
  555.   struct intString * is = sysCodes;
  556.  
  557.   /* This might need to do more processing eventually, i.e.
  558.    * if (prompt) { ... do more processing ... }
  559.    */
  560.   printf("_ID_\t__Name__ ____Description____\n");
  561.   while (is->i) {
  562.     printf("%3d\t%s\n", is->i, is->s);
  563.     is++;
  564.   }
  565. }
  566.